//============================================================================
// Name        : tree-match.cpp
// Author      : Long
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <boost/program_options.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

#include "dataset.h"
#include "covertree.h"

namespace po = boost::program_options;
po::options_description desc("Allowed options");
po::variables_map vm;

int n, d;
std::string fin, fout, ftree;

void process_options(int argc, char** argv);
void generateDataset();
void generateTree();
void usage(int exitcode = 0)
{
  std::cout << desc << std::endl;
  exit(exitcode);
}

int main(int argc, char** argv) {
  process_options(argc, argv);

  if (vm.count("gen"))
    generateDataset();
  else if (vm.count("tree"))
    generateTree();
  else
    usage();

	return 0;
}

void process_options(int argc, char** argv)
{
  desc.add_options()
    ("help", "produce this usage")
    ("gen", "generate random data")
    ("tree", "generate tree")
    ("randu", "uniform")
    ("randn", "normal")
    ("seed", "using different random seed")
    ("n", po::value<int>(&n)->default_value(10), "number of points")
    ("d", po::value<int>(&d)->default_value(2), "input dimension")
    ("in", po::value<std::string>(&fin)->default_value(""), "input file")
    ("out", po::value<std::string>(&fout)->default_value(""), "output file")
    ("treefile", po::value<std::string>(&ftree)->default_value(""), "tree file")
    ;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);
}

void generateDataset()
{
  if (fout.empty())
    {
      std::cout << "Need an output file name --out" << std::endl;
      usage(1);
    }
  Dataset data;
  Dataset::RAND_TYPE type = Dataset::RANDU;
  if (vm.count("randn"))
    type = Dataset::RANDN;
  if (vm.count("seed"))
    {
      sleep(10); // sleep 10 seconds for new random seed
      srand(time(NULL));
    }
  data.generate(n, d, type, arma::randu<vec>(d)*10-5, arma::randu<vec>(d)*10+1);
  data.save(fout);
}

void generateTree()
{
  if (fin.empty())
    {
      std::cout << "Need an input file name --in" << std::endl;
      usage(1);
    }
  if (fout.empty())
    {
      std::cout << "Need an output file name --out" << std::endl;
      usage(1);
    }
  Dataset data;
  data.load(fin);
//  for (int i = 0; i < data.n(); i++)
//    std::cout << data.get(i) << std::endl;

  CoverTree<Dataset> tree(data);
  if (ftree.empty())
    tree.buildTree();
  else
    tree.load(ftree);
  tree.dump();
  tree.save(fout);
}
